from flask import Blueprint, request, jsonify, render_template
from flask_login import login_required, current_user
from services.shared import db, NotificationConfig
from datetime import datetime
import hashlib
import hmac
import base64
import time
import requests
import json

notification_bp = Blueprint('notification', __name__)

@notification_bp.route('/notification-config')
@login_required
def notification_config_page():
    """通知配置页面"""
    return render_template('dashboard/notification_config.html')

@notification_bp.route('/api/notification-configs', methods=['GET'])
@login_required
def get_notification_configs():
    """获取用户的通知配置列表"""
    try:
        configs = NotificationConfig.query.filter_by(user_id=current_user.id).all()
        return jsonify({
            'success': True,
            'data': [config.to_dict() for config in configs]
        })
    except Exception as e:
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@notification_bp.route('/api/notification-configs/<int:config_id>', methods=['GET'])
@login_required
def get_notification_config(config_id):
    """获取单个通知配置"""
    try:
        config = NotificationConfig.query.filter_by(
            id=config_id, 
            user_id=current_user.id
        ).first()
        
        if not config:
            return jsonify({
                'success': False,
                'message': '配置不存在'
            }), 404
            
        return jsonify({
            'success': True,
            'data': config.to_dict()
        })
    except Exception as e:
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@notification_bp.route('/api/notification-configs', methods=['POST'])
@login_required
def create_notification_config():
    """创建通知配置"""
    try:
        data = request.get_json()
        
        # 验证必填字段
        if not data.get('name'):
            return jsonify({
                'success': False,
                'message': '配置名称不能为空'
            }), 400
            
        if not data.get('webhook_url'):
            return jsonify({
                'success': False,
                'message': 'Webhook地址不能为空'
            }), 400
        
        # 检查名称是否重复
        existing = NotificationConfig.query.filter_by(
            user_id=current_user.id,
            name=data['name']
        ).first()
        
        if existing:
            return jsonify({
                'success': False,
                'message': '配置名称已存在'
            }), 400
        
        # 创建配置
        is_enabled = data.get('is_enabled', True)
        if isinstance(is_enabled, str):
            is_enabled = is_enabled.lower() in ('true', '1', 'yes', 'on')
        
        config = NotificationConfig(
            user_id=current_user.id,
            name=data['name'],
            description=data.get('description', ''),
            webhook_url=data['webhook_url'].strip(),
            secret=data.get('secret', ''),
            is_enabled=is_enabled
        )
        
        db.session.add(config)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'data': config.to_dict(),
            'message': '配置创建成功'
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@notification_bp.route('/api/notification-configs/<int:config_id>', methods=['PUT'])
@login_required
def update_notification_config(config_id):
    """更新通知配置"""
    try:
        config = NotificationConfig.query.filter_by(
            id=config_id,
            user_id=current_user.id
        ).first()
        
        if not config:
            return jsonify({
                'success': False,
                'message': '配置不存在'
            }), 404
        
        data = request.get_json()
        
        # 验证必填字段
        if not data.get('name'):
            return jsonify({
                'success': False,
                'message': '配置名称不能为空'
            }), 400
            
        if not data.get('webhook_url'):
            return jsonify({
                'success': False,
                'message': 'Webhook地址不能为空'
            }), 400
        
        # 检查名称是否重复（排除当前配置）
        existing = NotificationConfig.query.filter_by(
            user_id=current_user.id,
            name=data['name']
        ).filter(NotificationConfig.id != config_id).first()
        
        if existing:
            return jsonify({
                'success': False,
                'message': '配置名称已存在'
            }), 400
        
        # 更新配置
        is_enabled = data.get('is_enabled', True)
        if isinstance(is_enabled, str):
            is_enabled = is_enabled.lower() in ('true', '1', 'yes', 'on')
            
        config.name = data['name']
        config.description = data.get('description', '')
        config.webhook_url = data['webhook_url'].strip()
        config.secret = data.get('secret', '')
        config.is_enabled = is_enabled
        config.updated_at = datetime.utcnow()
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'data': config.to_dict(),
            'message': '配置更新成功'
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@notification_bp.route('/api/notification-configs/<int:config_id>', methods=['DELETE'])
@login_required
def delete_notification_config(config_id):
    """删除通知配置"""
    try:
        config = NotificationConfig.query.filter_by(
            id=config_id,
            user_id=current_user.id
        ).first()
        
        if not config:
            return jsonify({
                'success': False,
                'message': '配置不存在'
            }), 404
        
        db.session.delete(config)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '配置删除成功'
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@notification_bp.route('/api/notification-configs/test', methods=['POST'])
@login_required
def test_notification_config():
    """测试通知配置（使用表单数据）"""
    try:
        data = request.get_json()
        
        if not data.get('webhook_url'):
            return jsonify({
                'success': False,
                'message': 'Webhook地址不能为空'
            }), 400
        
        # 发送测试消息
        success, message = send_dingtalk_message(
            webhook_url=data['webhook_url'],
            secret=data.get('secret', ''),
            title='测试通知',
            content=f'这是来自XbyJob的测试通知消息\n\n发送时间：{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}'
        )
        
        if success:
            return jsonify({
                'success': True,
                'message': '测试消息发送成功'
            })
        else:
            return jsonify({
                'success': False,
                'message': f'测试消息发送失败：{message}'
            }), 400
            
    except Exception as e:
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@notification_bp.route('/api/notification-configs/<int:config_id>/test', methods=['POST'])
@login_required
def test_notification_config_by_id(config_id):
    """测试通知配置（使用已保存的配置）"""
    try:
        config = NotificationConfig.query.filter_by(
            id=config_id,
            user_id=current_user.id
        ).first()
        
        if not config:
            return jsonify({
                'success': False,
                'message': '配置不存在'
            }), 404
        
        # 发送测试消息
        success, message = send_dingtalk_message(
            webhook_url=config.webhook_url,
            secret=config.secret,
            title='测试通知',
            content=f'这是来自XbyJob的测试通知消息\n\n配置名称：{config.name}\n发送时间：{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}'
        )
        
        if success:
            return jsonify({
                'success': True,
                'message': '测试消息发送成功'
            })
        else:
            return jsonify({
                'success': False,
                'message': f'测试消息发送失败：{message}'
            }), 400
            
    except Exception as e:
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

def generate_sign(secret, timestamp):
    """生成钉钉机器人加签"""
    string_to_sign = f'{timestamp}\n{secret}'
    hmac_code = hmac.new(
        secret.encode('utf-8'),
        string_to_sign.encode('utf-8'),
        digestmod=hashlib.sha256
    ).digest()
    sign = base64.b64encode(hmac_code).decode('utf-8')
    return sign

def send_dingtalk_message(webhook_url, secret, title, content):
    """发送钉钉消息"""
    try:
        # 构建消息体
        message = {
            "msgtype": "markdown",
            "markdown": {
                "title": title,
                "text": content
            }
        }
        
        # 如果有加签密钥，添加签名参数
        url = webhook_url
        if secret:
            timestamp = str(round(time.time() * 1000))
            sign = generate_sign(secret, timestamp)
            
            # 添加签名参数
            separator = '&' if '?' in url else '?'
            url = f"{url}{separator}timestamp={timestamp}&sign={sign}"
        
        # 发送请求
        headers = {'Content-Type': 'application/json'}
        response = requests.post(
            url,
            data=json.dumps(message),
            headers=headers,
            timeout=10
        )
        
        if response.status_code == 200:
            result = response.json()
            if result.get('errcode') == 0:
                return True, '发送成功'
            else:
                return False, result.get('errmsg', '未知错误')
        else:
            return False, f'HTTP错误：{response.status_code}'
            
    except requests.exceptions.Timeout:
        return False, '请求超时'
    except requests.exceptions.RequestException as e:
        return False, f'网络错误：{str(e)}'
    except Exception as e:
        return False, f'发送失败：{str(e)}'